import axios from 'axios'
import { ElMessage, ElMessageBox, ElLoading } from 'element-plus'
import router from '@/router'

// 创建axios实例
const service = axios.create({
  baseURL: process.env.VUE_APP_BASE_API || '/api', // api的base_url
  timeout: 15000, // 请求超时时间
  withCredentials: true // 跨域请求时发送cookies
})

// 全局loading实例
let loadingInstance = null
let loadingCount = 0

// 显示loading
function showLoading(config) {
  if (config.loading !== false) {
    loadingCount++
    if (loadingCount === 1) {
      loadingInstance = ElLoading.service({
        lock: true,
        text: config.loadingText || '加载中...',
        background: 'rgba(0, 0, 0, 0.7)'
      })
    }
  }
}

// 隐藏loading
function hideLoading() {
  loadingCount--
  if (loadingCount <= 0) {
    loadingCount = 0
    if (loadingInstance) {
      loadingInstance.close()
      loadingInstance = null
    }
  }
}

// 请求拦截器
service.interceptors.request.use(
  config => {
    // 显示loading
    showLoading(config)

    // 添加认证token
    const token = sessionStorage.getItem('token') || localStorage.getItem('token')
    if (token) {
      config.headers['Authorization'] = `Bearer ${token}`
    }

    // 添加用户信息
    const userInfo = sessionStorage.getItem('userInfo')
    if (userInfo) {
      try {
        const user = JSON.parse(userInfo)
        config.headers['X-User-Id'] = user.id || ''
        config.headers['X-User-Name'] = user.username || ''
      } catch (error) {
        console.warn('解析用户信息失败:', error)
      }
    }

    // 添加请求时间戳（防止缓存）
    if (config.method === 'get') {
      config.params = {
        ...config.params,
        _t: Date.now()
      }
    }

    // 设置Content-Type
    if (config.method === 'post' || config.method === 'put') {
      if (!config.headers['Content-Type']) {
        config.headers['Content-Type'] = 'application/json;charset=UTF-8'
      }
    }

    console.log('🚀 请求发送:', {
      url: config.url,
      method: config.method,
      params: config.params,
      data: config.data
    })

    return config
  },
  error => {
    hideLoading()
    console.error('❌ 请求错误:', error)
    ElMessage.error('请求配置错误')
    return Promise.reject(error)
  }
)

// 响应拦截器
service.interceptors.response.use(
  response => {
    hideLoading()

    const res = response.data
    const config = response.config

    console.log('✅ 响应接收:', {
      url: config.url,
      status: response.status,
      data: res
    })

    // 如果是下载文件，直接返回
    if (config.responseType === 'blob') {
      return response
    }

    // 根据后端约定的状态码处理
    const code = res.code || res.status || response.status

    // 成功状态码
    if (code === 200 || code === 0 || code === '200' || code === '0') {
      // 显示成功消息（可配置）
      if (config.showSuccessMsg && res.message) {
        ElMessage.success(res.message)
      }
      return res
    }

    // 特殊状态码处理
    switch (code) {
      case 401:
        ElMessage.error('登录已过期，请重新登录')
        handleLogout()
        return Promise.reject(new Error('登录已过期'))

      case 403:
        ElMessage.error('权限不足，无法访问')
        return Promise.reject(new Error('权限不足'))

      case 404:
        ElMessage.error('请求的资源不存在')
        return Promise.reject(new Error('资源不存在'))

      case 500:
        ElMessage.error('服务器内部错误')
        return Promise.reject(new Error('服务器错误'))

      case 502:
      case 503:
      case 504:
        ElMessage.error('服务器暂时不可用，请稍后重试')
        return Promise.reject(new Error('服务器不可用'))

      default:
        const message = res.message || res.msg || '请求失败'
        if (config.showErrorMsg !== false) {
          ElMessage.error(message)
        }
        return Promise.reject(new Error(message))
    }
  },
  error => {
    hideLoading()

    console.error('❌ 响应错误:', error)

    let message = '网络错误'

    if (error.response) {
      // 服务器返回错误状态码
      const status = error.response.status
      switch (status) {
        case 400:
          message = '请求参数错误'
          break
        case 401:
          message = '登录已过期，请重新登录'
          handleLogout()
          break
        case 403:
          message = '权限不足，无法访问'
          break
        case 404:
          message = '请求的资源不存在'
          break
        case 500:
          message = '服务器内部错误'
          break
        case 502:
          message = '网关错误'
          break
        case 503:
          message = '服务不可用'
          break
        case 504:
          message = '网关超时'
          break
        default:
          message = `服务器错误 ${status}`
      }
    } else if (error.request) {
      // 请求发出但没有收到响应
      if (error.code === 'ECONNABORTED') {
        message = '请求超时，请检查网络连接'
      } else {
        message = '网络连接失败，请检查网络'
      }
    } else {
      // 其他错误
      message = error.message || '未知错误'
    }

    // 显示错误消息（可配置）
    if (error.config && error.config.showErrorMsg !== false) {
      ElMessage.error(message)
    }

    return Promise.reject(error)
  }
)

// 处理登出
function handleLogout() {
  // 清除本地存储
  sessionStorage.clear()
  localStorage.removeItem('token')
  localStorage.removeItem('userInfo')

  // 跳转到登录页
  if (router.currentRoute.value.path !== '/login') {
    router.push('/login')
  }
}

// 导出axios实例
export default service

// 导出常用的请求方法
export const request = {
  // GET请求
  get(url, params = {}, config = {}) {
    return service({
      method: 'get',
      url,
      params,
      ...config
    })
  },

  // POST请求
  post(url, data = {}, config = {}) {
    return service({
      method: 'post',
      url,
      data,
      ...config
    })
  },

  // PUT请求
  put(url, data = {}, config = {}) {
    return service({
      method: 'put',
      url,
      data,
      ...config
    })
  },

  // DELETE请求
  delete(url, params = {}, config = {}) {
    return service({
      method: 'delete',
      url,
      params,
      ...config
    })
  },

  // 文件上传
  upload(url, formData, config = {}) {
    return service({
      method: 'post',
      url,
      data: formData,
      headers: {
        'Content-Type': 'multipart/form-data'
      },
      ...config
    })
  },

  // 文件下载
  download(url, params = {}, config = {}) {
    return service({
      method: 'get',
      url,
      params,
      responseType: 'blob',
      ...config
    })
  }
}
